﻿using System;
using System.ComponentModel;
using OpenCube.Model.Enums;
using OpenCube.Model.Enums.Converters;
using OpenCube.Model.Primitives;
using OpenCube.Model.Primitives.Converters;
using OpenCube.Nbt.Mapping.Attributes;
using OpenCube.Nbt.Mapping.Converters;

namespace OpenCube.Model
{
	public sealed class LevelDat
	{
		/// <summary>
		/// Gets or sets the NBT version of the level
		/// </summary>
		[NbtName("version")]
		public int Version { get; set; }

		/// <summary>
		/// Gets or sets if this world has been correctly initialized after creation.
		/// </summary>
		[NbtName("initialized")]
		public bool IsInitialized { get; set; }

		/// <summary>
		/// Gets the name of this level
		/// </summary>
		[NbtName("LevelName")]
		public string LevelName { get; set; }

		/// <summary>
		/// Gets or sets the (world) generator type.
		/// </summary>
		[NbtName("generatorName")]
		[NbtConverter(typeof(GeneratorTypeConverter))]
		public GeneratorType GeneratorType { get; set; }

		/// <summary>
		/// Gets or sets the (world) generator version
		/// </summary>
		[NbtName("generatorVersion")]
		public int GeneratorVersion { get; set; }

		/// <summary>
		/// Gets or sets the (world) generator options
		/// </summary>
		// TODO:
		public object GeneratorOptions { get; set; }

		/// <summary>
		/// Gets or sets the random seek for this level
		/// </summary>
		[Nbt]
		public long RandomSeed { get; set; }

		/// <summary>
		/// Gets or sets if the map generator should place structures such as villages.
		/// </summary>
		[Nbt]
		public bool MapFeatures { get; set; }

		/// <summary>
		/// The last time the game was played
		/// </summary>
		[Nbt]
		public DateTime LastPlayed { get; set; }

		/// <summary>
		/// Gets or sets if commands are allowed
		/// </summary>
		[NbtName("allowCommands")]
		public bool AllowCommands { get; set; }

		/// <summary>
		/// Gets or sets if the level is in hardcore mode.
		/// </summary>
		[NbtName("hardcore")]
		public bool IsHardcore { get; set; }

		/// <summary>
		/// Gets or sets the game type/mode.
		/// </summary>
		[NbtConverter(typeof(EnumIntegerConverter<GameType>))]
		public GameType GameType { get; set; }

		/// <summary>
		/// Gets or sets the difficulity level of the game, if locked to a difficulity.
		/// </summary>
		[DefaultValue(Difficulty.Normal)]
		[NbtConverter(typeof(EnumIntegerConverter<Difficulty>))]
		public Difficulty Difficulty { get; set; }

		/// <summary>
		/// Gets or sets if the difficulity of the game is locked, i.e. cannot be altered anymore.
		/// </summary>
		[NbtName("DifficultyLocked")]
		public bool IsDifficultyLocked { get; set; }

		/// <summary>
		/// Gets or sets the game time since start of the level.
		/// </summary>
		[NbtName("Time")]
		[NbtConverter(typeof(LongGameTimeSpanConverter))]
		public GameTimeSpan RunningTime { get; set; }

		/// <summary>
		/// Gets or sets the game time of day.
		/// </summary>
		[NbtName("DayTime")]
		[NbtConverter(typeof(LongGameTimeSpanConverter))]
		public GameTimeSpan TimeOfDay { get; set; }

		/// <summary>
		/// Gets or sets the spawn location
		/// </summary>
		[NbtConverter(typeof(CoordinatesConverter))]
		[NbtName("SpawnX", "SpawnY", "SpawnZ")]
		public Coordinates3<int> SpawnLocation { get; set; }

		/// <summary>
		/// Gest or sets the world border object
		/// </summary>
		[NbtFlatten]
		public WorldBorderDat WorldBorder { get; set; }

		/// <summary>
		/// Gets or sets if it is raining
		/// </summary>
		[NbtName("raining")]
		public bool IsRaining { get; set; }

		/// <summary>
		/// Gets or sets the time before rain is toggled.
		/// </summary>
		[NbtName("rainTime")]
		[NbtConverter(typeof(IntGameTimeSpanConverter))]
		public GameTimeSpan RainTime { get; set; }

		/// <summary>
		/// Getsor sets if the rain is a thunderstorm
		/// </summary>
		[NbtName("thundering")]
		public bool IsThundering { get; set; }

		/// <summary>
		/// Gets or sets the time before thunder is toggled.
		/// </summary>
		[NbtName("thunderTime")]
		[NbtConverter(typeof(IntGameTimeSpanConverter))]
		public GameTimeSpan ThunderTime { get; set; }

		/// <summary>
		/// Gets or sets the time the weather will stay clear.
		/// </summary>
		[NbtName("clearWeatherTime")]
		[NbtConverter(typeof(IntGameTimeSpanConverter))]
		public GameTimeSpan ClearWeatherTime { get; set; }

		/// <summary>
		/// Gets or sets the player for a single player game.
		/// </summary>
		[Nbt]
		public PlayerDat Player { get; set; }

		/// <summary>
		/// Gets or sets the game rules object.
		/// </summary>
		[Nbt]
		public GameRules GameRules { get; set; }
	}
}
